package com.ruoyi.app.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.app.domain.AppAsset;
import com.ruoyi.app.domain.bo.AppAssetBo;
import com.ruoyi.app.domain.bo.BuyGoodsBo;
import com.ruoyi.app.domain.vo.AppAssetVo;
import com.ruoyi.app.domain.vo.AppLevelRateVo;
import com.ruoyi.app.domain.vo.AppUserVo;
import com.ruoyi.app.mapper.AppAssetMapper;
import com.ruoyi.app.service.IAppAssetService;
import com.ruoyi.app.service.IAppDetailService;
import com.ruoyi.app.service.IAppLevelRateService;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BillType;
import com.ruoyi.common.enums.CoinType;
import com.ruoyi.common.enums.DetailEnums;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.redis.RedisUtils;
import com.ruoyi.system.service.ISysConfigService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.beans.Transient;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * APP用户资产信息Service业务层处理
 *
 * @author ruoyi
 * @date 2025-12-09
 */
@RequiredArgsConstructor
@Service
public class AppAssetServiceImpl implements IAppAssetService {

    private final AppAssetMapper baseMapper;
    private final IAppDetailService appDetailService;
    private final IAppLevelRateService appLevelRateService;
    private final ISysConfigService sysConfigService;

    /**
     * 查询APP用户资产信息
     */
    @Override
    public AppAssetVo queryById(Long id) {
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询APP用户资产信息
     */
    @Override
    public AppAssetVo queryByUid(Long uid) {
        QueryWrapper<AppAsset> asset = new QueryWrapper<>();
        asset.lambda().eq(AppAsset::getUserId, uid);
        return baseMapper.selectVoOne(asset);
    }

    /**
     * 查询APP用户资产信息列表
     */
    @Override
    public TableDataInfo<AppAssetVo> queryPageList(AppAssetBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<AppAsset> lqw = buildQueryWrapper(bo);
        Page<AppAssetVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询APP用户资产信息列表
     */
    @Override
    public List<AppAssetVo> queryList(AppAssetBo bo) {
        LambdaQueryWrapper<AppAsset> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    @Override
    public List<AppAssetVo> queryList(LambdaQueryWrapper<AppAsset> wrapper) {
        return baseMapper.selectVoList(wrapper);
    }

    private LambdaQueryWrapper<AppAsset> buildQueryWrapper(AppAssetBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<AppAsset> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getUserId() != null, AppAsset::getUserId, bo.getUserId());
        lqw.eq(StringUtils.isNotBlank(bo.getStatus()), AppAsset::getStatus, bo.getStatus());
        return lqw;
    }

    /**
     * 新增APP用户资产信息
     */
    @Override
    public Boolean insertByBo(AppAssetBo bo) {
        AppAsset add = BeanUtil.toBean(bo, AppAsset.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    @Override
    public Boolean insert(Long userId) {
        AppAssetBo assetBo = new AppAssetBo();
        assetBo.setIntegral(BigDecimal.ZERO);
        assetBo.setBalance(BigDecimal.ZERO);
        assetBo.setUserId(userId);
        assetBo.setStatus(Constants.SUCCESS);
        return insertByBo(assetBo);
    }

    /**
     * 修改APP用户资产信息
     */
    @Override
    public Boolean updateByBo(AppAssetBo bo) {
        AppAsset update = BeanUtil.toBean(bo, AppAsset.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(AppAsset entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除APP用户资产信息
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addBalance(Long uid, BigDecimal amount) {
        AppAssetVo appAssetVo = queryByUid(uid);
        LambdaUpdateWrapper<AppAsset> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.set(AppAsset::getBalance, appAssetVo.getBalance().add(amount.abs())).eq(AppAsset::getUserId, uid);
        return baseMapper.update(null, lambdaUpdateWrapper) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addIntegral(Long uid, BigDecimal amount) {
        AppAssetVo appAssetVo = queryByUid(uid);
        LambdaUpdateWrapper<AppAsset> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.set(AppAsset::getIntegral, appAssetVo.getIntegral().add(amount.abs())).eq(AppAsset::getUserId, uid);
        return baseMapper.update(null, lambdaUpdateWrapper) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addContribution(Long uid, BigDecimal amount) {
        AppAssetVo appAssetVo = queryByUid(uid);
        LambdaUpdateWrapper<AppAsset> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.set(AppAsset::getContribution, appAssetVo.getContribution().add(amount.abs())).eq(AppAsset::getUserId, uid);
        return baseMapper.update(null, lambdaUpdateWrapper) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addLiveness(Long uid, BigDecimal amount) {
        AppAssetVo appAssetVo = queryByUid(uid);
        LambdaUpdateWrapper<AppAsset> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.set(AppAsset::getLiveness, appAssetVo.getLiveness().add(amount.abs())).eq(AppAsset::getUserId, uid);
        return baseMapper.update(null, lambdaUpdateWrapper) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean subLiveness(Long uid, BigDecimal amount) {
        AppAssetVo appAssetVo = queryByUid(uid);
        LambdaUpdateWrapper<AppAsset> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.set(AppAsset::getLiveness, appAssetVo.getLiveness().subtract(amount.abs())).eq(AppAsset::getUserId, uid);
        return baseMapper.update(null, lambdaUpdateWrapper) > 0;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean subtractIntegral(Long uid, BigDecimal amount) {
        AppAssetVo appAssetVo = queryByUid(uid);
        BigDecimal amountAbs = amount.abs();
        if (appAssetVo.getIntegral().compareTo(amountAbs) < 0) {
            throw new ServiceException("账号资产不足!");
        }
        BigDecimal integral = appAssetVo.getIntegral().subtract(amountAbs);
        LambdaUpdateWrapper<AppAsset> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.set(AppAsset::getIntegral, integral).eq(AppAsset::getUserId, uid);
        return baseMapper.update(null, lambdaUpdateWrapper) > 0;
    }

    @Override
    public void addLiveIfAbsent(Long id, int i) {
        //判断是否加过
        String key = "liveIf:"+ id;
        //如果增加过则不再增加
        if (RedisUtils.hasKey(key)){
            return;
        }
        //增加1活跃度
        this.addLiveness(id, BigDecimal.ONE);
        //增加日志
        appDetailService.insert(id, new BigDecimal(1),
                BigDecimal.ZERO, BillType.IN.getCode(), CoinType.LIVENESS.getCode(),
                DetailEnums.BUY_TASK_REWARD.getCode(), "任务包进行中-奖励活跃度", null);
        RedisUtils.setCacheObject(key, "1");
    }

    @Override
    public boolean subContribution(Long userId, BigDecimal transferEndNumber) {
        AppAssetVo appAssetVo = queryByUid(userId);
        LambdaUpdateWrapper<AppAsset> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();

        BigDecimal bigDecimal = BigDecimal.ZERO;

        if (appAssetVo.getContribution().subtract(transferEndNumber.abs()).compareTo(BigDecimal.ZERO) > 0){
            bigDecimal = appAssetVo.getContribution().subtract(transferEndNumber.abs());
        }
        lambdaUpdateWrapper.set(AppAsset::getContribution,bigDecimal
                ).eq(AppAsset::getUserId, userId);
        return baseMapper.update(null, lambdaUpdateWrapper) > 0;
    }

    @Override
    public Boolean freeze(Long userId) {
        LambdaUpdateWrapper<AppAsset> appAssetLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        appAssetLambdaUpdateWrapper.set(AppAsset::getFreezeFlag, 1)
                .set(AppAsset::getFreezeEnd, LocalDateTime.now().plusDays(1))
                .eq(AppAsset::getUserId, userId);
        return baseMapper.update(null, appAssetLambdaUpdateWrapper) > 0;
    }

    @Override
    public List<AppAsset> selFee() {
        LambdaQueryWrapper<AppAsset> appAssetLambdaQueryWrapper = new LambdaQueryWrapper<>();
        appAssetLambdaQueryWrapper.eq(AppAsset::getFreezeFlag, 1);
        return baseMapper.selectList(appAssetLambdaQueryWrapper);
    }

    @Override
    public void unfreeze(Long userId) {
        LambdaUpdateWrapper<AppAsset> appAssetLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        appAssetLambdaUpdateWrapper.set(AppAsset::getFreezeFlag, 0)
                .set(AppAsset::getFreezeEnd, null)
                .eq(AppAsset::getUserId, userId);
        baseMapper.update(null, appAssetLambdaUpdateWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void buyGoods(BuyGoodsBo buyGoodsBo) {
        Long userId = LoginHelper.getUserId();
        if (!subtractBalance(userId, buyGoodsBo.getBalance())) {
            throw new ServiceException("账号资产不足!");
        }
        LambdaQueryWrapper<AppAsset> appAssetLambdaQueryWrapper = new LambdaQueryWrapper<>();
        appAssetLambdaQueryWrapper.eq(AppAsset::getUserId, userId);
        AppAssetVo appAssetVo = baseMapper.selectVoOne(appAssetLambdaQueryWrapper);

        baseMapper.update(null, new LambdaUpdateWrapper<AppAsset>()
                .set(AppAsset::getBalance, appAssetVo.getBalance().subtract(buyGoodsBo.getBalance()))
                .eq(AppAsset::getUserId, userId));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void coverBalance(BuyGoodsBo buyGoodsBo) {
        //积分兑换余额
        String open = sysConfigService.selectConfigByKey("app.jifen.ye");
        if (!StringUtils.equals(Constants.FAIL, open)) {
            throw new ServiceException("积分兑换余额功能已关闭!");
        }
        Long userId = LoginHelper.getUserId();
        AppAssetVo appAssetVo = queryByUid(userId);
        //查询手续费费率
        BigDecimal rate = appLevelRateService.userRate(userId);
        //算出手续费
        BigDecimal divide = buyGoodsBo.getBalance().multiply(rate).divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
        if (appAssetVo.getContribution().compareTo(buyGoodsBo.getBalance()) < 0){
            throw new ServiceException("贡献值不足!");
        }

        if (appAssetVo.getIntegral().compareTo(divide.add(buyGoodsBo.getBalance())) < 0){
            throw new ServiceException("积分不足!");
        }
        //扣除积分
        subtractIntegral(userId, divide.add(buyGoodsBo.getBalance()));
        //日志
        appDetailService.insert(userId,
                divide.add(buyGoodsBo.getBalance()),
                BigDecimal.ZERO, BillType.TO.getCode(), CoinType.INTE.getCode(),
                DetailEnums.TRANSFER11_GIVE.getCode(), "兑换余额扣除积分",
                userId);

        //扣除贡献值
        subContribution(userId, buyGoodsBo.getBalance());
        appDetailService.insert(userId,
                buyGoodsBo.getBalance(),
                BigDecimal.ZERO, BillType.TO.getCode(), CoinType.CONTRIBUTION.getCode(),
                DetailEnums.TRANSFER11_GIVE.getCode(), "兑换余额扣除贡献度",
                userId);


        //1积分=多少价格
        String bei = sysConfigService.selectConfigByKey("app.integral.price");
        //增加余额
        addBalance(userId, buyGoodsBo.getBalance().multiply(new BigDecimal(bei)));
        appDetailService.insert(userId,
                buyGoodsBo.getBalance().multiply(new BigDecimal(bei)),
                BigDecimal.ZERO, BillType.IN.getCode(), CoinType.GOLD.getCode(),
                DetailEnums.TRANSFER_INTEGRAL_GIVE.getCode(), "积分兑换余额",
                userId);

    }


    @Override
    public Boolean subtractBalance(Long uid, BigDecimal amount) {
        AppAssetVo appAssetVo = queryByUid(uid);
        if (appAssetVo.getBalance().compareTo(amount) < 0) {
            throw new ServiceException("账号资产不足!");
        }
        LambdaUpdateWrapper<AppAsset> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.set(AppAsset::getBalance, appAssetVo.getBalance().subtract(amount.abs())).eq(AppAsset::getUserId, uid);
        return baseMapper.update(null, lambdaUpdateWrapper) > 0;
    }
}
